﻿using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
#if TASKSUPPORT
using System.Threading.Tasks;
#endif
using System.Windows.Navigation;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MugenMvvmToolkit.Infrastructure;
using MugenMvvmToolkit.Interfaces;
using MugenMvvmToolkit.Interfaces.Models;
using MugenMvvmToolkit.Models;
using MugenMvvmToolkit.Utils;
using MugenMvvmToolkit.ViewModels;
using MugenMvvmToolkitTest.TestInfrastructure;
using MugenMvvmToolkitTest.TestModels;
using Should;

namespace MugenMvvmToolkitTest.Infrastructure
{
    [TestClass]
    public class NavigationProviderTest : TestBase
    {
        #region Nested type

        public class TestNavigableViewModel : NavigableViewModel, IHasOperationResultCallback
        {
            #region Properties

#if TASKSUPPORT
            public Func<INavigationContext, Task<bool>> OnNavigatingFromDelegate { get; set; }
#else
            public Func<INavigationContext, IOperationResult<bool>> OnNavigatingFromDelegate { get; set; }
#endif

            public Action<INavigationContext> OnNavigatedFromDelegate { get; set; }
            public Action<INavigationContext> OnNavigatedToDelegate { get; set; }

            #endregion

            #region Overrides of NavigableViewModel

#if TASKSUPPORT
            /// <summary>
            ///     Called when a page becomes the active page in a frame.
            /// </summary>
            /// <param name="context">
            ///     The specified <see cref="INavigationContext" />.
            /// </param>
            protected override Task<bool> OnNavigatingFrom(INavigationContext context)
            {
                if (OnNavigatingFromDelegate != null)
                    return OnNavigatingFromDelegate(context);
                return base.OnNavigatingFrom(context);
            }
#else
            /// <summary>
            ///     Called when a page becomes the active page in a frame.
            /// </summary>
            /// <param name="context">
            ///     The specified <see cref="INavigationContext" />.
            /// </param>
            protected override IOperationResult<bool> OnNavigatingFrom(INavigationContext context)
            {
                if (OnNavigatingFromDelegate != null)
                    return OnNavigatingFromDelegate(context);
                return base.OnNavigatingFrom(context);
            }
#endif
            /// <summary>
            ///     Called when a page is no longer the active page in a frame.
            /// </summary>
            protected override void OnNavigatedFrom(INavigationContext context)
            {
                if (OnNavigatedFromDelegate != null)
                    OnNavigatedFromDelegate(context);
            }

            /// <summary>
            ///     Called when a page becomes the active page in a frame.
            /// </summary>        
            protected override void OnNavigatedTo(INavigationContext context)
            {
                if (OnNavigatedToDelegate != null)
                    OnNavigatedToDelegate(context);
            }

            #endregion

            #region Implementation of IHasOperationResult

            /// <summary>
            ///     Gets or sets the operation result value.
            /// </summary>
            public bool? OperationResult { get; set; }

            #endregion

            #region Implementation of IHasOperationResultCallback

            public event Action<IHasOperationResultCallback, bool?> OperationResultChanged;

            public virtual void OnOperationResultChanged(bool? arg2)
            {
                var handler = OperationResultChanged;
                if (handler != null) handler(this, arg2);
            }

            #endregion
        }

        #endregion

        #region Fields

        private static readonly Dictionary<string, string> UriParameters = new Dictionary<string, string>
                                                                           {
                                                                               {
                                                                                   "key",
                                                                                   "value"
                                                                               },
                                                                               {
                                                                                   "key1",
                                                                                   "value1"
                                                                               }
                                                                           };

        private const string ViewName = "test";
        private static readonly Uri Uri = new Uri("/app;component/Test/view.xaml", UriKind.Relative);
        private static readonly Uri UriWithParameters = new Uri("/app;component/Test/view.xaml?key=value&key1=value1", UriKind.Relative);
        private static readonly ViewPageMappingItem PageMapping = new ViewPageMappingItem(Uri, typeof(TestNavigableViewModel), typeof(TestView), null);
        private static readonly ViewPageMappingItem PageMappingWithName = new ViewPageMappingItem(Uri, typeof(TestNavigableViewModel), typeof(TestView), ViewName);

        #endregion

        #region Properties

        protected TestViewPageMappingProvider ViewPageMappingProvider { get; set; }

        protected TestNavigationService NavigationService { get; set; }

        protected NavigationProvider NavigationProvider { get; set; }

        #endregion

        #region Test methods

        [TestMethod]
        public void ProviderShouldReturnsCurrentViewModelFromNavigationService()
        {
            var testView = new TestView();
            NavigationProvider.CurrentViewModel.ShouldBeNull();

            NavigationService.CurrentContent = testView;
            NavigationProvider.CurrentViewModel.ShouldBeNull();

            var viewModel = GetViewModel<TestNavigableViewModel>();
            testView.DataContext = viewModel;
            NavigationProvider.CurrentViewModel.ShouldEqual(viewModel);
        }

        [TestMethod]
        public void ProviderShouldNavigateToUri()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvoked = false;
#if SILVERLIGHT
            NavigationService.NavigateToUri = uri =>
            {
                uri.ShouldEqual(Uri);
                isInvoked = true;
                return true;
            };
            NavigationProvider.Navigate(Uri, null);
#else
            NavigationService.NavigateToUri = (uri, o) =>
                                                          {
                                                              o.ShouldBeNull();
                                                              uri.ShouldEqual(Uri);
                                                              isInvoked = true;
                                                              return true;
                                                          };
            NavigationProvider.Navigate(Uri, null, null);
#endif

            isInvoked.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldNavigateToUriAndMergeParameters()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvoked = false;
#if SILVERLIGHT
            NavigationService.NavigateToUri = uri =>
            {
                uri.ShouldEqual(UriWithParameters);
                isInvoked = true;
                return true;
            };
            NavigationProvider.Navigate(Uri, UriParameters);
#else
            NavigationService.NavigateToUri = (uri, o) =>
                                                          {
                                                              o.ShouldBeNull();
                                                              uri.ShouldEqual(UriWithParameters);
                                                              isInvoked = true;
                                                              return true;
                                                          };
            NavigationProvider.Navigate(Uri, null, UriParameters);
#endif

            isInvoked.ShouldBeTrue();
        }

#if WPF
        [TestMethod]
        public void ProviderShouldNavigateToUriWithObjParameter()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvoked = false;
            var parameter = new object();
            NavigationService.NavigateToUri = (uri, o) =>
                                              {
                                                  o.ShouldEqual(parameter);
                                                  isInvoked = true;
                                                  return true;
                                              };
            NavigationProvider.Navigate(Uri, parameter, UriParameters);
            isInvoked.ShouldBeTrue();
        }
#endif
        [TestMethod]
        public void ProviderShouldNavigateToViewModel()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvoked = false;
            bool isInvokedNavigate = false;
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) =>
                                                              {
                                                                  viewModel.ShouldBeType(type);
                                                                  s.ShouldBeNull();
                                                                  arg3.ShouldBeTrue();
                                                                  isInvoked = true;
                                                                  return PageMapping;
                                                              };
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item =>
            {
                item.ShouldEqual(PageMapping);
                isInvokedNavigate = true;
                return true;
            };
#else
            NavigationService.NavigateToMapping = (item, o) =>
                                                              {
                                                                  item.ShouldEqual(PageMapping);
                                                                  isInvokedNavigate = true;
                                                                  return true;
                                                              };
#endif

            NavigationProvider.Navigate(viewModel, null, null);
            isInvoked.ShouldBeTrue();
            isInvokedNavigate.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldNavigateToViewModelWithUriParameter()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvoked = false;
            bool isInvokedNavigate = false;
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) =>
                                                              {
                                                                  viewModel.ShouldBeType(type);
                                                                  s.ShouldBeNull();
                                                                  arg3.ShouldBeTrue();
                                                                  isInvoked = true;
                                                                  return PageMapping;
                                                              };
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item =>
            {
                item.Uri.ShouldEqual(UriWithParameters);
                item.ViewModelType.ShouldEqual(PageMapping.ViewModelType);
                item.ViewType.ShouldEqual(PageMapping.ViewType);
                item.Name.ShouldEqual(PageMapping.Name);
                isInvokedNavigate = true;
                return true;
            };
#else
            NavigationService.NavigateToMapping = (item, o) =>
                                                  {
                                                      item.Uri.ShouldEqual(UriWithParameters);
                                                      item.ViewModelType.ShouldEqual(PageMapping.ViewModelType);
                                                      item.ViewType.ShouldEqual(PageMapping.ViewType);
                                                      item.Name.ShouldEqual(PageMapping.Name);
                                                      isInvokedNavigate = true;
                                                      return true;
                                                  };
#endif

            NavigationProvider.Navigate(viewModel, UriParameters, null);
            isInvoked.ShouldBeTrue();
            isInvokedNavigate.ShouldBeTrue();
        }

#if WPF
        [TestMethod]
        public void ProviderShouldNavigateToViewModelWithObjParameter()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvoked = false;
            bool isInvokedNavigate = false;
            var parameter = new object();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) =>
                                                              {
                                                                  viewModel.ShouldBeType(type);
                                                                  s.ShouldBeNull();
                                                                  arg3.ShouldBeTrue();
                                                                  isInvoked = true;
                                                                  return PageMapping;
                                                              };
            NavigationService.NavigateToMapping = (item, o) =>
                                                  {
                                                      parameter.ShouldEqual(o);
                                                      item.ShouldEqual(PageMapping);
                                                      isInvokedNavigate = true;
                                                      return true;
                                                  };
            NavigationProvider.Navigate(viewModel, null, parameter);
            isInvoked.ShouldBeTrue();
            isInvokedNavigate.ShouldBeTrue();
        }
#endif


        [TestMethod]
        public void ProviderShouldNavigateToViewModelWithViewName()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvoked = false;
            bool isInvokedNavigate = false;
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) =>
            {
                viewModel.ShouldBeType(type);
                s.ShouldEqual(ViewName);
                arg3.ShouldBeTrue();
                isInvoked = true;
                return PageMappingWithName;
            };
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item =>
            {
                item.ShouldEqual(PageMappingWithName);
                isInvokedNavigate = true;
                return true;
            };
            NavigationProvider.Navigate(viewModel, null, ViewName);
#else
            NavigationService.NavigateToMapping = (item, o) =>
            {
                item.ShouldEqual(PageMappingWithName);
                isInvokedNavigate = true;
                return true;
            };
            NavigationProvider.Navigate(viewModel, null, null, ViewName);
#endif

            isInvoked.ShouldBeTrue();
            isInvokedNavigate.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldCallOnNavigatingFromMethodInPrevVm()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isCancelInvoked = false;
            bool isNavigatedInvoked = false;
            const NavigationMode mode = NavigationMode.Refresh;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForView = (type, arg) =>
            {
                newContent.ShouldBeType(type);
                return PageMapping;
            };
            viewModel.OnNavigatingFromDelegate = context =>
            {
                isCancelInvoked = true;
                context.NavigationProvider.ShouldEqual(NavigationProvider);
                context.NavigationMode.ShouldEqual(mode);
                context.Uri.ShouldEqual(Uri);
#if !SILVERLIGHT
                context.PageMapping.ShouldEqual(PageMapping);
#endif
                return MvvmExtensions.FromResult(false);
            };
            viewModel.OnNavigatedFromDelegate = context => isNavigatedInvoked = true;
            var view = new TestView { DataContext = viewModel };
            NavigationService.CurrentContent = view;
#if SILVERLIGHT
            var cancelArgs = new NavigatingCancelEventArgs(Uri, mode);
#else
            var cancelArgs = NavigationExtensions.CreateNavigatingCancelEventArgs(Uri, newContent, null, null, mode, null, null, false);
#endif

            cancelArgs.Cancel = false;
            NavigationService.OnNavigating(cancelArgs);
            cancelArgs.Cancel.ShouldBeTrue();
            isCancelInvoked.ShouldBeTrue();
            isNavigatedInvoked.ShouldBeFalse();
        }

        [TestMethod]
        public void ProviderShouldCallOnNavigatedFromMethodInPrevVmIfNavigatingTrue()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isCancelInvoked = false;
            bool isNavigatedInvoked = false;
            const NavigationMode mode = NavigationMode.Refresh;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForView = (type, arg) =>
            {
                newContent.ShouldBeType(type);
                return PageMapping;
            };
            viewModel.OnNavigatingFromDelegate = context =>
            {
                isCancelInvoked = true;
                return MvvmExtensions.FromResult(true);
            };
            viewModel.OnNavigatedFromDelegate = context =>
            {
                context.NavigationProvider.ShouldEqual(NavigationProvider);
                context.NavigationMode.ShouldEqual(mode);
                context.Uri.ShouldEqual(Uri);
#if !SILVERLIGHT
                context.PageMapping.ShouldEqual(PageMapping);
#endif
                isNavigatedInvoked = true;
            };
            var view = new TestView { DataContext = viewModel };
            NavigationService.CurrentContent = view;
#if SILVERLIGHT
            var cancelArgs = new NavigatingCancelEventArgs(Uri, mode);
#else
            var cancelArgs = NavigationExtensions.CreateNavigatingCancelEventArgs(Uri, newContent, null, null, mode, null, null, false);
#endif

            cancelArgs.Cancel = false;
            NavigationService.OnNavigating(cancelArgs);
            cancelArgs.Cancel.ShouldBeFalse();
            isCancelInvoked.ShouldBeTrue();
            isNavigatedInvoked.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldSetDataContextInVm()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvokedViewManager = false;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) => PageMapping;
            ViewManager.InitializeViewForViewModelDelegate = (model, view) =>
            {
                model.ShouldEqual(viewModel);
                view.ShouldEqual(newContent);
                isInvokedViewManager = true;
            };
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item => true;
            var navigatedArgs = new NavigationEventArgs(newContent, Uri);
#else
            NavigationService.NavigateToMapping = (item, o) => true;
            var navigatedArgs = NavigationExtensions.CreateNavigationEventArgs(Uri, newContent, null, null, null, false);
#endif
            NavigationProvider.Navigate(viewModel, null, null);
            NavigationService.OnNavigated(navigatedArgs);
            isInvokedViewManager.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldCallOnNavigatedToMethodInNavigatedViewModel()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            bool isNavigatedInvoked = false;
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) => PageMapping;
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item => true;
            var navigatedArgs = new NavigationEventArgs(newContent, Uri);
#else
            NavigationService.NavigateToMapping = (item, o) => true;
            var navigatedArgs = NavigationExtensions.CreateNavigationEventArgs(Uri, newContent, null, null, null, false);
#endif

            viewModel.OnNavigatedToDelegate = context =>
            {
                isNavigatedInvoked = true;
                context.IsAutoCreatedViewModel.ShouldBeFalse();
                context.NavigationMode.ShouldEqual(NavigationMode.New);
                context.PageMapping.ShouldEqual(PageMapping);
            };

            NavigationProvider.Navigate(viewModel, null, null);
            NavigationService.OnNavigated(navigatedArgs);
            isNavigatedInvoked.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldCompleteNavigationWhenNavigated()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) => PageMapping;
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item => true;
            var navigatedArgs = new NavigationEventArgs(newContent, Uri);
#else
            NavigationService.NavigateToMapping = (item, o) => true;
            var navigatedArgs = NavigationExtensions.CreateNavigationEventArgs(Uri, newContent, null, null, null, false);
#endif
            var navigationResult = NavigationProvider.Navigate(viewModel, null, null);
            navigationResult.NavigationResultTask.IsCompleted.ShouldBeFalse();
            NavigationService.OnNavigated(navigatedArgs);
            navigationResult.NavigationResultTask.IsCompleted.ShouldBeTrue();
            navigationResult.NavigationResultTask.Result.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldCreateVmUsingPageMappingWhenNavigateToUri()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            bool isInvokedViewManager = false;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            var func = IocAdapter.GetFunc;
            IocAdapter.GetFunc = (type, s, arg3) =>
            {
                if (type == typeof(TestNavigableViewModel))
                    return viewModel;
                return func(type, s, arg3);
            };
            ViewPageMappingProvider.FindMappingForView = (type, arg) =>
            {
                newContent.ShouldBeType(type);
                return PageMapping;
            };
            ViewManager.InitializeViewForViewModelDelegate = (model, view) =>
            {
                model.ShouldEqual(viewModel);
                view.ShouldEqual(newContent);
                isInvokedViewManager = true;
            };
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item => true;
            var navigatedArgs = new NavigationEventArgs(newContent, Uri);
#else
            NavigationService.NavigateToMapping = (item, o) => true;
            var navigatedArgs = NavigationExtensions.CreateNavigationEventArgs(Uri, newContent, null, null, null, false);
#endif
            NavigationService.OnNavigated(navigatedArgs);
            isInvokedViewManager.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldCompleteOperationWhenVmNavigatedBackAndDefaultPolicy()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) => PageMapping;
            ViewPageMappingProvider.FindMappingForView = (type, s) => PageMapping;
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item => true;
            var navigatedArgs = new NavigationEventArgs(newContent, Uri);
            var cancelArgs = new NavigatingCancelEventArgs(Uri, NavigationMode.Back);
#else
            NavigationService.NavigateToMapping = (item, o) => true;
            var navigatedArgs = NavigationExtensions.CreateNavigationEventArgs(Uri, newContent, null, null, null, false);
            var cancelArgs = NavigationExtensions.CreateNavigatingCancelEventArgs(Uri, newContent, null, null, NavigationMode.Back, null, null, false);
#endif


            var navigationResult = NavigationProvider.Navigate(viewModel, null, null);
            NavigationService.OnNavigated(navigatedArgs);
            NavigationService.CurrentContent = newContent;
            newContent.DataContext = viewModel;

            navigationResult.OperationResultTask.IsCompleted.ShouldBeFalse();
            viewModel.OperationResult = true;
            NavigationService.OnNavigating(cancelArgs);
            navigationResult.OperationResultTask.IsCompleted.ShouldBeTrue();
            navigationResult.OperationResultTask.Result.Value.ShouldBeTrue();
        }

        [TestMethod]
        public void ProviderShouldNotCompleteOperationWhenPolicyIsNull()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            NavigationProvider = new NavigationProvider(NavigationService, ViewModelProvider, ViewPageMappingProvider,
                ViewManager, ThreadManager, null, null);
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) => PageMapping;
            ViewPageMappingProvider.FindMappingForView = (type, s) => PageMapping;
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item => true;
            var navigatedArgs = new NavigationEventArgs(newContent, Uri);
            var cancelArgs = new NavigatingCancelEventArgs(Uri, NavigationMode.Back);
#else
            NavigationService.NavigateToMapping = (item, o) => true;
            var navigatedArgs = NavigationExtensions.CreateNavigationEventArgs(Uri, newContent, null, null, null, false);
            var cancelArgs = NavigationExtensions.CreateNavigatingCancelEventArgs(Uri, newContent, null, null, NavigationMode.Back, null, null, false);
#endif
            var navigationResult = NavigationProvider.Navigate(viewModel, null, null);
            NavigationService.OnNavigated(navigatedArgs);
            NavigationService.CurrentContent = newContent;
            newContent.DataContext = viewModel;

            navigationResult.OperationResultTask.IsCompleted.ShouldBeFalse();
            viewModel.OperationResult = true;
            NavigationService.OnNavigating(cancelArgs);
            navigationResult.OperationResultTask.IsCompleted.ShouldBeFalse();
        }

        [TestMethod]
        public void ProviderShouldNotCompleteOperationWhenVmNotBackNavigated()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) => PageMapping;
            ViewPageMappingProvider.FindMappingForView = (type, s) => PageMapping;
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item => true;
            var navigatedArgs = new NavigationEventArgs(newContent, Uri);
            var cancelArgs = new NavigatingCancelEventArgs(Uri, NavigationMode.New);
#else
            NavigationService.NavigateToMapping = (item, o) => true;
            var navigatedArgs = NavigationExtensions.CreateNavigationEventArgs(Uri, newContent, null, null, null, false);
            var cancelArgs = NavigationExtensions.CreateNavigatingCancelEventArgs(Uri, newContent, null, null, NavigationMode.New, null, null, false);
#endif
            var navigationResult = NavigationProvider.Navigate(viewModel, null, null);
            NavigationService.OnNavigated(navigatedArgs);
            NavigationService.CurrentContent = newContent;
            newContent.DataContext = viewModel;

            navigationResult.OperationResultTask.IsCompleted.ShouldBeFalse();
            viewModel.OperationResult = true;
            NavigationService.OnNavigating(cancelArgs);
            navigationResult.OperationResultTask.IsCompleted.ShouldBeFalse();
        }

        [TestMethod]
        public void ProviderShouldCompleteOperationWhenDefaultPolicyAndVmCallCallback()
        {
            ThreadManager.ImmediateInvokeInUi = true;
            var newContent = new TestView();
            var viewModel = GetViewModel<TestNavigableViewModel>();
            ViewPageMappingProvider.FindMappingForViewModel = (type, s, arg3) => PageMapping;
            ViewPageMappingProvider.FindMappingForView = (type, s) => PageMapping;
#if SILVERLIGHT
            NavigationService.NavigateToMapping = item => true;
            var navigatedArgs = new NavigationEventArgs(newContent, Uri);
#else
            NavigationService.NavigateToMapping = (item, o) => true;
            var navigatedArgs = NavigationExtensions.CreateNavigationEventArgs(Uri, newContent, null, null, null, false);
#endif
            var navigationResult = NavigationProvider.Navigate(viewModel, null, null);
            NavigationService.OnNavigated(navigatedArgs);
            navigationResult.OperationResultTask.IsCompleted.ShouldBeFalse();
            viewModel.OnOperationResultChanged(false);
            navigationResult.OperationResultTask.IsCompleted.ShouldBeTrue();
            navigationResult.OperationResultTask.Result.Value.ShouldBeFalse();
        }

        #endregion

        #region Overrides of TestBase

        protected override void OnInit()
        {
            base.OnInit();
            NavigationService = new TestNavigationService();
            ViewPageMappingProvider = new TestViewPageMappingProvider();
            NavigationProvider = new NavigationProvider(NavigationService, ViewModelProvider, ViewPageMappingProvider,
                ViewManager, ThreadManager, new DefaultNavigationOperationResultPolicy());
        }

        #endregion
    }
}